﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Data.OleDb;
using AliCMS.SystemModule;

namespace AliCMS.TemplateEngine
{
    internal class Menu : Tag
    {
        internal Menu(Engine engine, int index, int length, int contentIndex, int contentLength, Tag parent)
            : base(engine, index, length, contentIndex, contentLength, parent)
        {
        }

        internal override void Init()
        {
            #region 获取Row,Col和Record
            foreach (Tag tag in ChildTags)
            {
                if (tag is Row)
                {
                    _row = tag;
                    break;
                }

                if (tag is Col)
                {
                    _col = tag;
                    break;
                }

                if (tag is Record)
                {
                    _record = tag;
                    break;
                }
            }

            if (_row != null || _col != null)
            {
                if (_row != null && _col == null)
                {
                    if (_row.ChildTags[0] is Col)
                    {
                        _col = _row.ChildTags[0];
                    }
                    else if (_row.ChildTags[0] is Record)
                    {
                        _record = _row.ChildTags[0];
                    }
                    else if (!(_row.ChildTags[0] is Separator))
                    {
                        Exception exp = new Exception("lang_parse_template_row_just_include_col_record");
                        Engine.ReportError(exp, _row.Index);
                    }
                }

                if (_record == null)
                {
                    if (_col.ChildTags[0] is Record)
                    {
                        _record = _col.ChildTags[0];
                    }
                    else if (!(_col.ChildTags[0] is Separator))
                    {
                        Exception exp = new Exception("lang_parse_template_col_just_include_record");
                        Engine.ReportError(exp, _col.Index);
                    }
                }
            }
            #endregion

            #region 获取Select, SelectYes, SelectNo
            _select = null;
            foreach (Tag tag in _record.ChildTags)
            {
                if (tag is Select)
                {
                    _select = tag;
                    break;
                }
            }

            if (_select != null)
            {
                foreach (Tag tag in _select.ChildTags)
                {
                    if (tag is Yes)
                        _selectYes = tag;
                    else if (tag is No)
                        _selectNo = tag;
                }
            }
            #endregion

            Regex re = null;
            Match match = null;

            #region Mark
            _mark = String.Empty;
            re = new Regex("Mark=\"(?<v>.*?)\"", RegexOptions.Compiled);
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
            {
                _mark = match.Groups["v"].Value;
            }
            else
            {
                if (Engine.IsMultiSite)
                    _mark = "Site";
                else
                    _mark = "System";
            }
            #endregion

            #region Module
            _module = Engine.GetModuleByMark(_mark);
            #endregion

            #region ObjectID
            _object = Manager.Objects.Select(Alias.Module.Object.Namespace + "='" + _module[Alias.Module.Namespace] + "' and FullName='Menu'")[0];
            /*            
            DataTable objectList = Engine.GetObjectList(_module[Alias.Module.Namespace].ToString());
            DataRow[] rows = objectList.Select(Alias.Module.Object.Name + "='Menu' and " + Alias.Module.Object.ParentID + "='" + Guid.Empty + "'");
            if (rows.Length == 0)
            {
                Exception exp = new Exception("lang_parse_template_cant_find_menu_object");
                Engine.ReportError(exp, Index);
            }

            _object = rows[0];
            */
            #endregion

            #region id
            _id = Id;
            if (String.IsNullOrEmpty(_id))
                _id = UniqueName + "ID";
            #endregion

            #region SelectExactly
            _selectExactly = "false";
            re = new Regex("Select=\"Exactly\"");
            match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
                _selectExactly = "true";
            #endregion

            #region 需要处理的子标签输出表达式
            if (_record != null)
            {
                _aliasStatment = new StringBuilder();
                _statment = new StringBuilder();
                _complex = new StringBuilder();
                _repeatCheckList = new List<string>();
                InitAliasStatment(_record.ChildTags);
            }
            #endregion
        }
        internal override void Parse()
        {
            ParseToCode();
            ParseToXml();
        }
        internal override string ParseVariable(Expression variable)
        {
            string result = null;

            Match match = Regex.Match(variable.Value, @"((?<id>[a-zA-Z_]\w*)\[(?<counter>(\d+)|([a-zA-Z_]\w*))\]\[(?<name>[a-zA-Z_]\w*)\])|((?<id>[a-zA-Z_]\w*)\[(?<name>[a-zA-Z_]\w*)\])|(\[(?<name>[a-zA-Z_]\w*)\])|(?<name>[a-zA-Z_]\w*)");
            if (!match.Success)
                return result;

            if (match.Groups["id"].Success && match.Groups["id"].Value != Id)
                return result;

            if (match.Groups["name"].Value == "URL")
            {
                return UniqueName + "BuildUrl(record)";
            }
            else
            {
                DataRow[] rows = Manager.Properties.Select(Alias.Module.Object.Property.ObjectID + "='" + _object[Alias.Module.Object.ID] + "' and " + Alias.Module.Object.Property.Name + "='" + match.Groups["name"].Value + "'");
                if (rows.Length == 0)
                {
                    if (match.Groups["name"].Value == "Index")
                    {
                        result = variable.Value.Remove(match.Index, match.Length);
                        return result.Insert(match.Index, _id + "Counter");
                    }
                    else if (match.Groups["name"].Value == "Count")
                    {
                        result = variable.Value.Remove(match.Index, match.Length);
                        return result.Insert(match.Index, _id + ".Rows.Count");
                    }
                    else if (match.Groups["name"].Value == "Record")
                    {
                        result = variable.Value.Remove(match.Index, match.Length);
                        return result.Insert(match.Index, "(" + _id + "Record as System.Data.DataRow)");
                    }
                    else
                    {
                        return result;
                    }
                }

                string counter = String.Empty;
                if (match.Groups["counter"].Success)
                {
                    if (match.Groups["counter"].Value == "SelectedIndex")
                        counter = UniqueName + "SelectedIndex";
                    else
                        counter = match.Groups["counter"].Value;
                }
                else
                {
                    counter = _id + "Counter";
                }

                result = variable.Value.Remove(match.Index, match.Length);
                return result.Insert(match.Index, _id + ".Rows[" + counter + "][" + _module[Alias.Module.Namespace] + ".Alias.Menu." + match.Groups["name"].Value + "]");
            }
        }

        private void InitAliasStatment(List<Tag> childTags)
        {
            foreach (Tag tag in childTags)
            {
                if (tag is List || tag is Tree)
                    continue;

                if (!(tag is OutputStatment))
                {
                    InitAliasStatment(tag.ChildTags);
                    continue;
                }

                OutputStatment osTag = tag as OutputStatment;

                string content = Engine.Text.Substring(osTag.ContentIndex, osTag.ContentLength);
                if (content == "Index")
                {
                    osTag.IsAliasStatment = true;
                    osTag.AliasXml = content;
                    osTag.AliasCode = "null";

                    if (_repeatCheckList.Contains(content))
                        continue;

                    _aliasStatment.Append("replacementPair[\"{#" + osTag.AliasXml + "#}\"] = " + osTag.AliasCode + ";");
                }
                else if (content == "URL")
                {
                    osTag.IsAliasStatment = true;
                    osTag.AliasXml = content;

                    if (_repeatCheckList.Contains(content))
                        continue;

                    _aliasStatment.Append(@"
                                        replacementPair[""{#URL#}""] = new CustomBuild(
                                                                        delegate(DataRow record, int index)
                                                                        {
                                                                            return " + UniqueName + @"BuildUrl(record);
                                                                        }
                                                                        );
                                                ");
                }
                else if (Manager.Properties.Select(Alias.Module.Object.Property.ObjectID + "='" + _object[Alias.Module.Object.ID] + "' and " + Alias.Module.Object.Property.Name + "='" + content + "'").Length == 1)
                {
                    osTag.IsAliasStatment = true;
                    osTag.AliasXml = content;
                    osTag.AliasCode = _module[Alias.Module.Namespace] + ".Alias." + _object[Alias.Module.Object.Name] + "." + content;

                    if (_repeatCheckList.Contains(content))
                        continue;

                    _aliasStatment.Append("replacementPair[\"{#" + osTag.AliasXml + "#}\"] = " + osTag.AliasCode + ";");
                }
                else if (content.StartsWith("[") && content.EndsWith("]"))
                {
                    osTag.IsAliasStatment = true;
                    osTag.AliasXml = content;
                    osTag.AliasCode = content.Substring(1, content.Length - 2);

                    if (_repeatCheckList.Contains(content))
                        continue;

                    _aliasStatment.Append("replacementPair[\"{#" + osTag.AliasXml.Replace("\"", "\\\"") + "#}\"] = " + osTag.AliasCode + ";");
                }

                if (osTag.IsAliasStatment)
                    _repeatCheckList.Add(content);
            }
        }
        private StringBuilder ParseCondition()
        {
            StringBuilder result = new StringBuilder();
            result.Append("string condition = null;\r\n");
            Regex re = new Regex("Condition=\"(?<v>.*?)\"", RegexOptions.Compiled);
            Match match = null;
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
            {
                DataRow[] properties = Manager.Properties.Select(Alias.Module.Object.Property.ObjectID + "='" + _object[Alias.Module.Object.ID] + "'");

                #region 排序
                DataTable propertyTable = new DataTable();
                propertyTable.Columns.Add("Name", typeof(string));
                propertyTable.Columns.Add("Alias", typeof(string));
                propertyTable.Columns.Add("OleDbType", typeof(byte));
                propertyTable.Columns.Add("Width", typeof(int));

                foreach (DataRow property in properties)
                {
                    DataRow newRow = propertyTable.NewRow();
                    newRow["Name"] = property[Alias.Module.Object.Property.Name];
                    newRow["Alias"] = property[Alias.Module.Object.Property.UniqueInnerID];
                    newRow["OleDbType"] = property[Alias.Module.Object.Property.OleDbType];
                    newRow["Width"] = newRow["Name"].ToString().Length;
                    propertyTable.Rows.Add(newRow);
                }

                properties = propertyTable.Select("", "Width DESC");
                #endregion

                #region 获取类型
                Dictionary<int, OleDbType> types = new Dictionary<int, OleDbType>();
                MatchCollection matches = Regex.Matches(match.Groups["v"].Value, @"(?<n>[a-zA-Z_]\w*)\s?(=|>|<|<>|>=|<=)\s?(?<v>[a-zA-Z_]\w*\[[a-zA-Z_]\w*\])");
                foreach (Match m in matches)
                {
                    DataRow[] rows = propertyTable.Select("Name='" + m.Groups["n"].Value + "'");
                    if (rows.Length == 0 || Convert.IsDBNull(rows[0]["OleDbType"]))
                        continue;

                    types.Add(m.Groups["v"].Index, (OleDbType)(byte)rows[0]["OleDbType"]);
                }
                #endregion

                bool hasLastParenthis = false;
                int start = 0;
                int end = 0;
                matches = Regex.Matches(match.Groups["v"].Value, @"(\)?\s+(and|or)\s+(\(\s?)?)?(?<n>\w+)\s*(>=|<=|<>|=|>|<|LIKE|IS NOT|IS)\s*", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                for (int i = 0; i < matches.Count; i++)
                {
                    System.Text.RegularExpressions.Group nameGroup = matches[i].Groups["n"];
                    string name = nameGroup.Value;
                    string alias = name;
                    foreach (DataRow property in properties)
                    {
                        if (property["Name"].ToString() == name)
                        {
                            alias = property["Alias"].ToString();
                            break;
                        }
                    }

                    string temp = matches[i].Value.Remove(nameGroup.Index - matches[i].Index, nameGroup.Length);
                    temp = temp.Insert(nameGroup.Index - matches[i].Index, alias);
                    result.Append("condition += \"" + temp + "\";\r\n");

                    start = matches[i].Index + matches[i].Length;
                    if (i < matches.Count - 1)
                        end = matches[i + 1].Index;
                    else
                        end = match.Groups["v"].Value.Length;
                    string value = match.Groups["v"].Value.Substring(start, end - start);

                    if (i == matches.Count - 1 && value.EndsWith(")"))
                    {
                        value = value.Remove(value.Length - 1);
                        hasLastParenthis = true;
                    }

                    #region IS NULL
                    if (String.IsNullOrEmpty(value))
                        continue;
                    #endregion

                    #region 已知常量
                    if (Regex.IsMatch(value, @"^(false|true|NULL|\d+|\{?[a-fA-F0-9]{8}(-?[a-fA-F0-9]{4}){3}-?[a-fA-F0-9]{12}\}?|'[^']*')$", RegexOptions.Compiled | RegexOptions.IgnoreCase))
                    {
                        result.Append("condition += \"" + value + "\";\r\n");
                        continue;
                    }
                    #endregion

                    DataRow[] rows = propertyTable.Select("Name='" + name + "'");
                    if (rows.Length == 0 || Convert.IsDBNull(rows[0]["OleDbType"]))
                    {
                        result.Append("condition += " + Engine.ParseExpression(this.Parent == null ? this : this.Parent, value) + ";\r\n");
                    }
                    else
                    {
                        OleDbType type = (OleDbType)(byte)rows[0]["OleDbType"];
                        if (type == OleDbType.Guid)
                        {
                            result.Append("object v" + i + " = " + Engine.ParseExpression(this.Parent == null ? this : this.Parent, value) + ";");
                            result.Append(@"
                                            if (v" + i + @" == null)
                                                condition = condition.Substring(0, condition.Length - " + temp.Length + @");
                                            else if (v" + i + @".ToString() == String.Empty)
                                                condition = condition.Substring(0, condition.Length - 1) + "" IS NULL "";
                                            else
                                                condition += v" + i + @".ToString();
                                            ");
                        }
                        else if (type == OleDbType.BSTR || type == OleDbType.Char || type == OleDbType.LongVarChar || type == OleDbType.LongVarWChar || type == OleDbType.VarChar || type == OleDbType.VarWChar || type == OleDbType.WChar)
                        {
                            result.Append("condition += \"'\" + " + Engine.ParseExpression(this.Parent == null ? this : this.Parent, value) + " + \"'\";\r\n");
                        }
                        else if (type == OleDbType.Date || type == OleDbType.DBDate || type == OleDbType.DBTime || type == OleDbType.DBTimeStamp)
                        {
                            result.Append("condition += \"#\" + Convert.ToDateTime(" + Engine.ParseExpression(this.Parent == null ? this : this.Parent, value) + ").ToString(\"yyyy-MM-dd HH:mm:ss\") + \"#\";\r\n");
                        }
                        else
                        {
                            result.Append("condition += " + Engine.ParseExpression(this.Parent == null ? this : this.Parent, value) + ";\r\n");
                        }
                    }
                }

                if (matches.Count == 0)
                    result.Append("condition += " + Engine.ParseExpression(this.Parent == null ? this : this.Parent, match.Groups["v"].Value) + ";\r\n");

                if (hasLastParenthis)
                    result.Append("condition += \")\";");
            }

            #region 如果是站群，并且当前对象包含SubInstanceID，则限制SubInstanceID
            if (Engine.IsMultiSite)
            {
                DataRow[] rows = Manager.Properties.Select(Alias.Module.Object.Property.ObjectID + "='" + _object[Alias.Module.Object.ID] + "' AND " + Alias.Module.Object.Property.Name + "='SubInstanceID'");
                if (rows.Length > 0)
                {
                    result.Append(@"
                                if (condition == null || !condition.Contains(""" + rows[0][Alias.Module.Object.Property.UniqueInnerID] + @"""))
                                {
                                    condition += "" AND " + rows[0][Alias.Module.Object.Property.UniqueInnerID] + @"="" + Request.QueryString[""DynamicSiteSubInstanceID""];
                                }
                                ");
                }
            }
            #endregion

            return result;
        }
        private void ParseToCode()
        {
            StringBuilder result = new StringBuilder();
            Regex re = null;
            Match match = null;

            #region Page
            string page = "-1";
            re = new Regex("Page=\"(?<v>.*?)\"", RegexOptions.Compiled);
            match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
            {
                page = match.Groups["v"].Value;
                if (!Regex.IsMatch(page, @"^\d+$"))
                    page = "Convert.ToInt32(" + Engine.ParseExpression(this, page) + ")";
            }
            #endregion

            #region PageSize
            string pageSize = "-1";
            re = new Regex("PageSize=\"(?<v>.*?)\"", RegexOptions.Compiled);
            match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
            {
                pageSize = match.Groups["v"].Value;
                if (!Regex.IsMatch(pageSize, @"^\d+$"))
                    pageSize = "Convert.ToInt32(" + Engine.ParseExpression(this, pageSize) + ")";
            }
            #endregion

            #region Condition
            StringBuilder condition = ParseCondition();
            #endregion

            #region Sort
            StringBuilder sort = new StringBuilder();
            sort.Append("string sort = null;");
            re = new Regex("Sort=\"(?<v>.*?)\"", RegexOptions.Compiled);
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
            {
                DataRow[] properties = Manager.Properties.Select(Alias.Module.Object.Property.ObjectID + "='" + _object[Alias.Module.Object.ID] + "'");

                bool find = false;
                StringBuilder value = new StringBuilder();
                string[] items = match.Groups["v"].Value.Split(',');
                foreach (string item in items)
                {
                    find = false;
                    string[] pair = item.Trim().Split(' ');
                    foreach (DataRow property in properties)
                    {
                        string alias = property[Alias.Module.Object.Property.UniqueInnerID].ToString();
                        string name = property[Alias.Module.Object.Property.Name].ToString();
                        if (name == pair[0])
                        {
                            if (value.Length != 0)
                                value.Append(",");

                            if (pair.Length > 1)
                                value.Append(alias + pair[1]);
                            else
                                value.Append(alias);

                            find = true;
                            break;
                        }
                    }

                    if (!find)
                        break;
                }

                if (find)
                    sort.Append("sort = \"" + value + "\";");
                else
                    sort.Append("sort = " + Engine.ParseExpression(this, match.Groups["v"].Value) + ";");
            }
            #endregion

            #region RowSeparator
            StringBuilder rowSeparatorReplacement = new StringBuilder();
            if (_row != null)
            {
                foreach (Tag tag in _row.ChildTags)
                {
                    if (tag is Separator)
                    {
                        foreach (Tag separatorChildTag in tag.ChildTags)
                        {
                            if (separatorChildTag is Code)
                            {
                                rowSeparatorReplacement.Append(separatorChildTag.ResultCode);
                            }
                            else if (tag is OutputStatment)
                            {
                                result.Append("object " + tag.UniqueName + " = " + tag.ResultCode + ";\r\n");
                                result.Append(UniqueName + " = " + UniqueName + ".Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + " == null ? \"\" : " + tag.UniqueName + ".ToString());\r\n");
                            }
                            else if (separatorChildTag is IfStatment)
                            {
                                rowSeparatorReplacement.Append(separatorChildTag.ResultCode);
                                rowSeparatorReplacement.Append("rowSeparator = rowSeparator.Replace(\"{#" + separatorChildTag.UniqueName + "#}\"," + separatorChildTag.UniqueName + ");\r\n");
                            }
                            else if (separatorChildTag.ResultCode != null && Regex.IsMatch(separatorChildTag.ResultCode, "protected string " + separatorChildTag.UniqueName + @"\s+{\s+get\s+"))
                            {
                                rowSeparatorReplacement.Append("rowSeparator = rowSeparator.Replace(\"{#" + separatorChildTag.UniqueName + "#}\"," + separatorChildTag.UniqueName + ");\r\n");
                            }
                        }
                    }
                }
            }
            #endregion

            #region ColSeparator
            StringBuilder colSeparatorReplacement = new StringBuilder();
            if (_col != null)
            {
                foreach (Tag tag in _row.ChildTags)
                {
                    if (tag is Separator)
                    {
                        foreach (Tag separatorChildTag in tag.ChildTags)
                        {
                            if (separatorChildTag is Code)
                            {
                                colSeparatorReplacement.Append(separatorChildTag.ResultCode);
                            }
                            else if (tag is OutputStatment)
                            {
                                result.Append("object " + tag.UniqueName + " = " + tag.ResultCode + ";\r\n");
                                result.Append(UniqueName + " = " + UniqueName + ".Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + " == null ? \"\" : " + tag.UniqueName + ".ToString());\r\n");
                            }
                            else if (separatorChildTag is IfStatment)
                            {
                                colSeparatorReplacement.Append(separatorChildTag.ResultCode);
                                colSeparatorReplacement.Append("colSeparator = colSeparator.Replace(\"{#" + separatorChildTag.UniqueName + "#}\"," + separatorChildTag.UniqueName + ");\r\n");
                            }
                            else if (separatorChildTag.ResultCode != null && Regex.IsMatch(separatorChildTag.ResultCode, "protected string " + separatorChildTag.UniqueName + @"\s+{\s+get\s+"))
                            {
                                colSeparatorReplacement.Append("colSeparator = colSeparator.Replace(\"{#" + separatorChildTag.UniqueName + "#}\"," + separatorChildTag.UniqueName + ");\r\n");
                            }
                        }
                    }
                }
            }
            #endregion

            #region Select
            StringBuilder select = new StringBuilder();
            if (_selectYes != null || _selectNo != null)
            {
                #region YesReplacement
                StringBuilder yesReplacement = new StringBuilder();
                if (_selectYes != null)
                {
                    foreach (Tag tag in _selectYes.ChildTags)
                    {
                        if (tag is Code)
                        {
                            yesReplacement.Append(tag.ResultCode);
                        }
                        else if (tag.ResultCode != null && Regex.IsMatch(tag.ResultCode, "protected string " + tag.UniqueName + @"\s+{\s+get\s+"))
                        {
                            yesReplacement.Append("selectedYes.Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + ");\r\n");
                        }
                        else if (tag is IfStatment)
                        {
                            yesReplacement.Append(tag.ResultCode);
                            yesReplacement.Append("selectedYes.Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + ");\r\n");
                        }
                    }
                }
                #endregion

                #region NoReplacement
                StringBuilder noReplacement = new StringBuilder();
                if (_selectNo != null)
                {
                    foreach (Tag tag in _selectNo.ChildTags)
                    {
                        if (tag is Code)
                        {
                            noReplacement.Append(tag.ResultCode);
                        }
                        else if (tag.ResultCode != null && Regex.IsMatch(tag.ResultCode, "protected string " + tag.UniqueName + @"\s+{\s+get\s+"))
                        {
                            noReplacement.Append("selectedNo.Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + ");\r\n");
                        }
                        else if (tag is IfStatment)
                        {
                            noReplacement.Append(tag.ResultCode);
                            noReplacement.Append("selectedNo.Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + ");\r\n");
                        }
                    }
                }
                #endregion

                result.Append(@"
                            private int <%Name%>SelectedIndex_ = -1;
                            protected int <%Name%>SelectedIndex
                            {
                                get
                                {
                                    if (<%Name%>SelectedIndex_ != -1)
                                        return <%Name%>SelectedIndex_;

                                    string pageUrl = <%URL%>;
                                    if (<%SelectExactly%>)
                                    {
                                        for (int i = 0; i < <%ID%>.Rows.Count; i++)
                                        {
                                            string url = <%Name%>BuildUrl(<%ID%>.Rows[i]);
                                            if (url == pageUrl)
                                            {
                                                <%Name%>SelectedIndex_ = i;
                                                break;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        List<string> urls = null;
                                        string dir = pageUrl;
                                        while (<%Name%>SelectedIndex_ == -1 && dir.Length > 0)
                                        {
                                            int slash = dir.LastIndexOf('/');
                                            if (slash == -1)
                                                break;

                                            dir = dir.Substring(0, slash);

                                            for (int i = 0; i < <%ID%>.Rows.Count; i++)
                                            {
                                                if (urls == null)
                                                    urls = new List<string>();
                                                if (i > urls.Count - 1)
                                                    urls.Add(<%Name%>BuildUrl(<%ID%>.Rows[i]));

                                                if (urls[i].StartsWith(dir + ""/""))
                                                {
                                                    string remain = urls[i].Substring(dir.Length + 1);
                                                    if (remain == pageUrl.Substring(dir.Length + 1))
                                                    {
                                                        <%Name%>SelectedIndex_ = i;
                                                        break;
                                                    }

                                                    if (remain.Length == 0 || remain.StartsWith(""index""))
                                                    {
                                                        <%Name%>SelectedIndex_ = i;
                                                        continue;
                                                    }
                                                }
                                            }
                                        };
                                    }

                                    /*
                                    string selectedURL = null;
                                    int maxCount = 0;
                                    for (int i = 0; i < <%ID%>.Rows.Count; i++)
                                    {
                                        string url = <%Name%>BuildUrl(<%ID%>.Rows[i]);
                                        if (<%SelectExactly%>)
                                        {
                                            if (url == pageUrl)
                                            {
                                                <%Name%>SelectedIndex_ = i;
                                                break;
                                            }
                                        }
                                        else
                                        {
                                            int count = 0;
                                            for (int j = 0; j < url.Length && j < pageUrl.Length; j++)
                                            {
                                                if (url[j] == pageUrl[j])
                                                    count++;
                                                else
                                                    break;
                                            }

                                            if (count >= maxCount)
                                            {
                                                if (count == maxCount && selectedURL != null && selectedURL.Length < url.Length)
                                                    continue;

                                                <%Name%>SelectedIndex_ = i;
                                                selectedURL = url;
                                                maxCount = count;
                                            }
                                        }
                                    }
                                    */

                                    return <%Name%>SelectedIndex_;
                                }
                            }
                            private int <%Name%>SelectedID = -1;
                            private string <%Name%>IsSelected(DataRow record)
                            {
                                if (<%Name%>SelectedID == -1 && <%Name%>SelectedIndex != -1)
                                    <%Name%>SelectedID = (int)<%ID%>.Rows[<%Name%>SelectedIndex][" + _module[Alias.Module.Namespace] + @".Alias.Menu.InnerID];

                                int id = (int)<%ID%>.Rows[<%ID%>Counter][" + _module[Alias.Module.Namespace] + @".Alias.Menu.InnerID];
                                if (<%Name%>SelectedID == id)
                                {
                                    StringBuilder selectedYes = new StringBuilder(_xmlTemplate.SelectSingleNode(""//<%Name%>/Select/Yes"").InnerText);
                                    <%YesReplacement%>
                                    return selectedYes.ToString();
                                }
                                else
                                {
                                    StringBuilder selectedNo = new StringBuilder(_xmlTemplate.SelectSingleNode(""//<%Name%>/Select/No"").InnerText);
                                    <%NoReplacement%>
                                    return selectedNo.ToString();
                                }
                            }
                          ");
                
                result.Replace("<%URL%>", "BuildUrl(null, null, null)");
                result.Replace("<%SelectExactly%>", _selectExactly);
                result.Replace("<%YesReplacement%>", yesReplacement.ToString());
                result.Replace("<%NoReplacement%>", noReplacement.ToString());

                _complex.Append(@"
                                        replacementPair[""{#" + _select.UniqueName + @"#}""] = new CustomBuild(
                                                                        delegate(DataRow record, int index)
                                                                        {
                                                                            return " + UniqueName + @"IsSelected(record);
                                                                        }
                                                                        );
                                                ");
            }
            #endregion

            #region RecordReplacement
            StringBuilder recordReplacement = new StringBuilder();
            if (_record != null)
            {
                MakeRecordReplacementCode(_record);

                recordReplacement.Append(_complex);
                recordReplacement.Append(_statment);
                recordReplacement.Append(_aliasStatment);
            }
            #endregion

            #region AllReplacement
            StringBuilder allReplacement = new StringBuilder();
            foreach (Tag tag in ChildTags)
            {
                if (tag is Row || tag is Col || tag is Record)
                    continue;

                if (tag is Code)
                {
                    allReplacement.Append(tag.ResultCode);
                }
                else if (tag is OutputStatment)
                {
                    allReplacement.Append("object " + tag.UniqueName + " = " + tag.ResultCode + ";\r\n");
                    allReplacement.Append("all.Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + " == null ? \"\" : " + tag.UniqueName + ".ToString());\r\n");
                }
                else if (tag is IfStatment)
                {
                    allReplacement.Append(tag.ResultCode);
                    allReplacement.Append("all.Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + ");\r\n");
                }
                else if (tag.ResultCode != null && Regex.IsMatch(tag.ResultCode, "protected string " + tag.UniqueName + @"\s+{\s+get\s+"))
                {
                    allReplacement.Append("all.Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + ");\r\n");
                }
            }
            #endregion

            #region Menu自定义BuildUrl
            if (_mark == "System")
            {
                result.Append(@"
                            private string <%Name%>BuildUrl(DataRow record)
                            {
                                string linkType = record[AliCMS.SystemModule.Alias.Menu.LinkType].ToString();
                                string url = record[AliCMS.SystemModule.Alias.Menu.Path].ToString();
                                if (linkType == ""OuterLink"")
                                {
									//注：不再考虑Fake404。彻底没有问题时，才移除下面注释的代码
                                    //if (url.StartsWith(""/"") && (Convert.ToBoolean(Manager.Site[AliCMS.SystemModule.Alias.InstanceConfig.Fake404]) || Request.RawUrl.IndexOf(""/alicms.aspx?/"") != -1))
                                    //    return Manager.GetWebPath() + ""alicms.aspx?"" + url;
                                    //else
                                        return url;
                                }

                                DataRow[] rows = Manager.Channels.Select(AliCMS.SystemModule.Alias.Channel.ID + ""='"" + record[AliCMS.SystemModule.Alias.Menu.ChannelID] + ""'"");
                                if (rows.Length == 0)
                                    return url;

                                DataRow channel = rows[0];
                                if (!Convert.IsDBNull(Channel[AliCMS.SystemModule.Alias.Channel.TranslateLang]))
                                {
                                    string condition = AliCMS.SystemModule.Alias.Channel.ID + "" IS NOT NULL AND "" + AliCMS.SystemModule.Alias.Channel.TemplateLang + ""='"" + Channel[AliCMS.SystemModule.Alias.Channel.TemplateLang] + ""' AND "" + AliCMS.SystemModule.Alias.Channel.TranslateLang + ""='"" + Channel[AliCMS.SystemModule.Alias.Channel.TranslateLang] + ""'"";
                                    if (Convert.IsDBNull(channel[AliCMS.SystemModule.Alias.Instance.ID]))
                                        condition += "" AND "" + AliCMS.SystemModule.Alias.Instance.ID + "" IS NULL"";
                                    else
                                        condition += "" AND "" + AliCMS.SystemModule.Alias.Instance.ID + ""='"" + channel[AliCMS.SystemModule.Alias.Instance.ID] + ""'"";

                                    string parent = null;
                                    if (Convert.IsDBNull(channel[AliCMS.SystemModule.Alias.Channel.ParentID]))
                                        parent = "" AND "" + AliCMS.SystemModule.Alias.Channel.ParentID + "" IS NULL"";
                                    else
                                        parent = "" AND "" + AliCMS.SystemModule.Alias.Channel.ParentID + ""='"" + channel[AliCMS.SystemModule.Alias.Channel.ParentID] + ""'"";

                                    rows = Manager.Channels.Select(condition + parent);
                                    if (rows.Length > 0)
                                    {
                                        channel = rows[0];
                                    }
                                    else if (!Convert.IsDBNull(channel[AliCMS.SystemModule.Alias.Channel.ParentID]))
                                    {
                                        DataRow parentChannel = Manager.Channels.Select(AliCMS.SystemModule.Alias.Channel.ID + ""='"" + channel[AliCMS.SystemModule.Alias.Channel.ParentID] + ""'"")[0];
                                        if (Convert.IsDBNull(parentChannel[AliCMS.SystemModule.Alias.Channel.ParentID]))
                                            parent = "" AND "" + AliCMS.SystemModule.Alias.Channel.ParentID + "" IS NULL"";
                                        else
                                            parent = "" AND "" + AliCMS.SystemModule.Alias.Channel.ParentID + ""='"" + parentChannel[AliCMS.SystemModule.Alias.Channel.ParentID] + ""'"";
                                        rows = Manager.Channels.Select(condition + parent);
                                        if (rows.Length > 0)
                                        {
                                            parent = "" AND "" + AliCMS.SystemModule.Alias.Channel.ParentID + ""='"" + rows[0][AliCMS.SystemModule.Alias.Channel.ID] + ""'"";
                                            rows = Manager.Channels.Select(condition + parent);
                                            if (rows.Length == 0)
                                            {
                                                channel = rows[0];
                                            }
                                            else if (rows.Length > 0)
                                            {
                                                int index = 0;
                                                DataRow[] siblings = Manager.Channels.Select(AliCMS.SystemModule.Alias.Channel.ParentID + ""='"" + channel[AliCMS.SystemModule.Alias.Channel.ParentID] + ""'"");
                                                for (int i = 0; i < siblings.Length; i++)
                                                {
                                                    if (siblings[i] == channel)
                                                    {
                                                        if (rows.Length > i)
                                                            channel = rows[i];
                                                        else
                                                            channel = rows[0];
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }

                                if (linkType == ""Content"")
                                {
									string content = record[AliCMS.SystemModule.Alias.Menu.Content].ToString();
                                    if (!Convert.IsDBNull(record[AliCMS.SystemModule.Alias.Menu.PageTemplate]))
                                    {
                                        url = BuildUrl(channel, record[AliCMS.SystemModule.Alias.Menu.PageTemplate].ToString(), ""ID="" + record[AliCMS.SystemModule.Alias.Menu.PageID]);
                                    }
                                    else
                                    {
                                        rows = Manager.Pages.Select(AliCMS.SystemModule.Alias.Template.Page.TemplatePath + ""='"" + channel[AliCMS.SystemModule.Alias.Channel.TemplatePath] + ""' AND "" + AliCMS.SystemModule.Alias.Template.Page.Mark + ""='System' AND "" + AliCMS.SystemModule.Alias.Template.Page.Object + ""='Menu'"");
                                        if (rows.Length == 0)
                                        {
                                            url = String.Empty;
                                        }
                                        else
                                        {
                                            url = BuildUrl(channel, rows[0][AliCMS.SystemModule.Alias.Template.Page.PathInTemplate].ToString(), ""ID="" + record[AliCMS.SystemModule.Alias.Menu.PageID]);
                                        }
                                    }
                                }
                                else
                                {
                                    string channelPath = String.Empty;
                                    if (!String.IsNullOrEmpty(channel[AliCMS.SystemModule.Alias.Channel.Domain].ToString()))
                                    {
                                        Uri domain = new Uri(channel[AliCMS.SystemModule.Alias.Channel.Domain].ToString().Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries)[0]);
                                        if (channel == Channel)
                                            channelPath = <%Debug3%>domain.LocalPath;
                                        else
                                            channelPath = <%Debug4%>;
                                    }
                                    else if (!String.IsNullOrEmpty(Channel[AliCMS.SystemModule.Alias.Channel.Domain].ToString()))
                                    {
                                       channelPath = Manager.Site[AliCMS.SystemModule.Alias.InstanceConfig.Domain].ToString()<%Debug2%> + channel[AliCMS.SystemModule.Alias.Channel.Path].ToString().TrimStart('/');
                                    }
                                    else
                                    {
                                        channelPath = channel[AliCMS.SystemModule.Alias.Channel.Path].ToString();
                                        <%Debug1%>
                                    }
                                    #region 包含正则表达式情况
                                    if (channelPath.IndexOf('{') != -1)
                                    {
                                        System.Text.RegularExpressions.Match match = System.Text.RegularExpressions.Regex.Match(channelPath, ""\\{(?<name>\\w+)(:.*?)?(?<!\\\\)\\}"");
                                        if (match.Success && !String.IsNullOrEmpty(Request.QueryString[match.Groups[""name""].Value]))
                                        {
                                            channelPath = channelPath.Remove(match.Index, match.Length).Insert(match.Index, Request.QueryString[match.Groups[""name""].Value]);
                                        }
                                    }
                                    #endregion
                                    if (!String.IsNullOrEmpty(url))
                                    {
                                        url = channelPath + url;
                                        url = url.Replace("".ext"", channel[AliCMS.SystemModule.Alias.Channel.Extension].ToString());
                                    }
                                    else
                                    {
                                        url = channelPath + channel[AliCMS.SystemModule.Alias.Channel.DefaultDocument].ToString() + channel[AliCMS.SystemModule.Alias.Channel.Extension];
                                    }

									//注：不再考虑Fake404。彻底没有问题时，才移除下面注释的代码
                                    //if (Convert.ToBoolean(Manager.Site[AliCMS.SystemModule.Alias.InstanceConfig.Fake404]) || Request.RawUrl.IndexOf(""/alicms.aspx?/"") != -1)
                                    //    url = Manager.GetWebPath() + ""alicms.aspx?"" + url;
                                }

                                return url;
                            }
                            ");
            }
            else
            {
                result.Append(@"
                            private string <%Name%>BuildUrl(DataRow record)
                            {
                                string linkType = record[" + _module[Alias.Module.Namespace] + @".Alias.Menu.Type].ToString();
                                string url = record[" + _module[Alias.Module.Namespace] + @".Alias.Menu.Path].ToString();
                                if (linkType == ""OuterLink"")
                                {
                                    return url;
                                }

								if (SubChannels == null)//单一模板模式
								{
									if (linkType == ""Content"")
									{
										string content = record[" + _module[Alias.Module.Namespace] + @".Alias.Menu.Content].ToString();
										if (!Convert.IsDBNull(record[" + _module[Alias.Module.Namespace] + @".Alias.Menu.PageTemplate]))
										{
											url = BuildUrl(null, record[" + _module[Alias.Module.Namespace] + @".Alias.Menu.PageTemplate].ToString(), ""ID="" + record[" + _module[Alias.Module.Namespace] + @".Alias.Menu.PageID]);
										}
									}
									else
									{
										string channelPath = SubWebPath;

										if (!String.IsNullOrEmpty(url))
										{
											url = channelPath + url;
											url = url.Replace("".ext"", Channel[AliCMS.SystemModule.Alias.Channel.Extension].ToString());
										}
										else
										{
											url = channelPath + Channel[AliCMS.SystemModule.Alias.Channel.DefaultDocument].ToString() + Channel[AliCMS.SystemModule.Alias.Channel.Extension];
										}
									}

									return url;
								}
								else
								{
									DataRow[] rows = SubChannels.Select(" + _module[Alias.Module.Namespace] + @".Alias.Channel.ID + ""='"" + record[" + _module[Alias.Module.Namespace] + @".Alias.Menu.ChannelID] + ""'"");
									if (rows.Length == 0)
										return url;

									DataRow channel = rows[0];

									if (linkType == ""Content"")
									{
										string content = record[" + _module[Alias.Module.Namespace] + @".Alias.Menu.Content].ToString();
										if (!Convert.IsDBNull(record[" + _module[Alias.Module.Namespace] + @".Alias.Menu.PageTemplate]))
										{
											url = BuildUrl(channel, record[" + _module[Alias.Module.Namespace] + @".Alias.Menu.PageTemplate].ToString(), ""ID="" + record[" + _module[Alias.Module.Namespace] + @".Alias.Menu.PageID]);
										}
										else
										{
											rows = Manager.Pages.Select(AliCMS.SystemModule.Alias.Template.Page.TemplatePath + ""='"" + channel[AliCMS.SystemModule.Alias.Channel.TemplatePath] + ""' AND "" + AliCMS.SystemModule.Alias.Template.Page.Object + ""='Menu'"");
											if (rows.Length == 0)
											{
												url = String.Empty;
											}
											else
											{
												url = BuildUrl(channel, rows[0][AliCMS.SystemModule.Alias.Template.Page.PathInTemplate].ToString(), ""ID="" + record[" + _module[Alias.Module.Namespace] + @".Alias.Menu.PageID]);
											}
										}
									}
									else
									{
										string channelPath = SubWebPath + channel[" + _module[Alias.Module.Namespace] + @".Alias.Channel.Path].ToString();
										<%Debug1%>

										if (!String.IsNullOrEmpty(url))
										{
											url = channelPath + url;
											url = url.Replace("".ext"", Channel[AliCMS.SystemModule.Alias.Channel.Extension].ToString());
										}
										else
										{
											url = channelPath + Channel[AliCMS.SystemModule.Alias.Channel.DefaultDocument].ToString() + Channel[AliCMS.SystemModule.Alias.Channel.Extension];
										}
									}

									return url;
								}
                            }
                            ");
            }
            #endregion

            #region 写入相关变量
            result.Append(@"

                            private int <%ID%>Counter = 0;
                            private object <%ID%>Record = null;
                            protected DataTable <%ID%>;
                        ");
            #endregion

            #region 写入<%ID%>_
            if (_mark == "System")
            {
                result.Append(@"
                                private DataTable <%ID%>_
                                {
                                    get
                                    {
                                        <%Condition%>

                                        <%Sort%>

                                        using (AliCMS.SystemModule.IMenu bll = (AliCMS.SystemModule.IMenu)Manager.CreateObject(""Menu"", SystemInstanceID, PageLang, false))
                                        {
                                            <%ID%> = bll.List(<%Page%>, <%PageSize%>, condition, sort);
                                        }

                                        return <%ID%>;
                                    }
                                }
                        ");
            }
            else
            {
                result.Append(@"
                                private DataTable <%ID%>_
                                {
                                    get
                                    {
                                        <%Condition%>

                                        <%Sort%>

                                        using (AliCMS.SiteModule.IMenu bll = (AliCMS.SiteModule.IMenu)Manager.CreateObject(""Menu"", InstanceID, PageLang, false))
                                        {
                                            <%ID%> = bll.List(<%Page%>, <%PageSize%>, condition, sort);
                                        }

                                        return <%ID%>;
                                    }
                                }
                        ");
            }
            #endregion

            result.Append(@"
                            protected string <%Name%>
                            {
                                get
                                {
                                    XmlNode node = _xmlTemplate.SelectSingleNode(""//<%Name%>"");
                                    Dictionary<string, object> replacementPair = new Dictionary<string, object>();
                                    <%RecordReplacement%>
                                    StringBuilder all = Manager.Build(node, <%ID%>_, replacementPair, ref <%ID%>Record, ref <%ID%>Counter);
                                    <%RowSeparatorReplacement%>
                                    <%ColSeparatorReplacement%>
                                    <%AllReplacement%>
                                    return all.ToString();
                                }
                            }
                          ");
            result.Replace("<%ID%>", _id);
            result.Replace("<%Name%>", UniqueName);
            result.Replace("<%Condition%>", condition.ToString());
            result.Replace("<%Sort%>", sort.ToString());
            result.Replace("<%Page%>", page);
            result.Replace("<%PageSize%>", pageSize);
            result.Replace("<%RowSeparatorReplacement%>", rowSeparatorReplacement.ToString());
            result.Replace("<%ColSeparatorReplacement%>", colSeparatorReplacement.ToString());
            result.Replace("<%RecordReplacement%>", recordReplacement.ToString());
            result.Replace("<%AllReplacement%>", allReplacement.ToString());
            if (Engine.Debug)
            {
                result.Replace("<%Debug1%>", "channelPath = channelPath.Insert(Manager.GetWebPath().Length, \"debug/\");");
                result.Replace("<%Debug2%>", " + \"debug/\"");
                result.Replace("<%Debug3%>", "\"/debug\" + ");
				result.Replace("<%Debug4%>", "domain.Scheme + \"://\" + domain.Host + (domain.IsDefaultPort ? \"\" : \":\" + domain.Port) + \"/debug\" + domain.LocalPath");
            }
            else
            {
                result.Replace("<%Debug1%>", "");
                result.Replace("<%Debug2%>", "");
                result.Replace("<%Debug3%>", "");
                result.Replace("<%Debug4%>", "domain.ToString()");
            }
            ResultCode = result.ToString();
        }
        private void ParseToXml()
        {
            if (ChildTags.Count == 0)
                return;

            #region Record和RecordSeparator
            _yesXml = new StringBuilder();
            _noXml = new StringBuilder();
            _recordSeparatorXml = new StringBuilder();
            StringBuilder record = new StringBuilder();
            if (_record != null)
            {
                record.Append(Engine.Text.Substring(_record.ContentIndex, _record.ContentLength));
                MakeRecordReplacementXml(_record, record);
                record.Append("{#Record#}");
            }
            #endregion

            #region Col，ColSeparator，MaxRecord
            StringBuilder col = new StringBuilder();
            StringBuilder colSeparator = new StringBuilder();
            string maxRecord = "0";
            if (_col == null)
            {
                col.Append("{#Record#}");
            }
            else
            {
                Regex re = new Regex("MaxRecord=\"(?<v>.*?)\"", RegexOptions.Compiled);
                Match match = re.Match(Engine.Text, _col.Index, _col.ContentIndex - _col.Index);
                if (match.Success)
                    maxRecord = match.Groups["v"].Value;

                col.Append(Engine.Text.Substring(_col.ContentIndex, _col.ContentLength));
                for (int i = _col.ChildTags.Count - 1; i >= 0; i--)
                {
                    Tag tag = _col.ChildTags[i];
                    col.Remove(tag.Index - _col.ContentIndex, tag.Length);
                    if (tag is Separator)
                    {
                        colSeparator.Append(Engine.Text.Substring(tag.ContentIndex, tag.ContentLength));
                        for (int j = tag.ChildTags.Count - 1; j >= 0; j--)
                        {
                            Tag separatorChild = tag.ChildTags[j];
                            colSeparator.Remove(separatorChild.Index - tag.ContentIndex, separatorChild.Length);
                            if (separatorChild is IfStatment || (separatorChild.ResultCode != null && Regex.IsMatch(separatorChild.ResultCode, "protected string " + separatorChild.UniqueName + @"\s+{\s+get\s+")))
                                colSeparator.Insert(separatorChild.Index - tag.ContentIndex, "{#" + separatorChild.UniqueName + "#}");
                        }

                    }
                    else if (tag is Record)
                    {
                        col.Insert(tag.Index - _col.ContentIndex, "{#Record#}");
                    }
                }
            }
            col.Append("{#Col#}");
            #endregion

            #region Row，RowSeparator，MaxCol
            StringBuilder row = new StringBuilder();
            StringBuilder rowSeparator = new StringBuilder();
            string maxCol = "0";
            if (_row == null)
            {
                row.Append("{#Col#}");
            }
            else
            {
                Regex re = new Regex("MaxCol=\"(?<v>.*?)\"", RegexOptions.Compiled);
                Match match = re.Match(Engine.Text, _row.Index, _row.ContentIndex - _row.Index);
                if (match.Success)
                    maxCol = match.Groups["v"].Value;

                row.Append(Engine.Text.Substring(_row.ContentIndex, _row.ContentLength));
                for (int i = _row.ChildTags.Count - 1; i >= 0; i--)
                {
                    Tag tag = _row.ChildTags[i];
                    row.Remove(tag.Index - _row.ContentIndex, tag.Length);
                    if (tag is Separator)
                    {
                        rowSeparator.Append(Engine.Text.Substring(tag.ContentIndex, tag.ContentLength));
                        for (int j = tag.ChildTags.Count - 1; j >= 0; j--)
                        {
                            Tag separatorChild = tag.ChildTags[j];
                            rowSeparator.Remove(separatorChild.Index - tag.ContentIndex, separatorChild.Length);
                            if (separatorChild is IfStatment || (separatorChild.ResultCode != null && Regex.IsMatch(separatorChild.ResultCode, "protected string " + separatorChild.UniqueName + @"\s+{\s+get\s+")))
                                rowSeparator.Insert(separatorChild.Index - tag.ContentIndex, "{#" + separatorChild.UniqueName + "#}");
                        }

                    }
                    else if (tag is Col || tag is Record)
                    {
                        row.Insert(tag.Index - _row.ContentIndex, "{#Col#}");
                    }
                }
            }
            row.Append("{#Row#}");
            #endregion

            #region All
            StringBuilder all = new StringBuilder(Engine.Text.Substring(ContentIndex, ContentLength));
            for (int i = ChildTags.Count - 1; i >= 0; i--)
            {
                Tag tag = ChildTags[i];
                all.Remove(tag.Index - ContentIndex, tag.Length);
                if (tag is Row || tag is Col || tag is Record)
                    all.Insert(tag.Index - ContentIndex, "{#Row#}");
                else if (tag is IfStatment || (tag.ResultCode != null && Regex.IsMatch(tag.ResultCode, "protected string " + tag.UniqueName + @"\s+{\s+get\s+")))
                    all.Insert(tag.Index - ContentIndex, "{#" + tag.UniqueName + "#}");
            }
            #endregion

            #region 生成Xml
            StringBuilder result = new StringBuilder();
            result.Append(@"
		                <Select>
		                    <Yes>
			                    <![CDATA[<%Yes%>]]>
		                    </Yes>
		                    <No>
			                    <![CDATA[<%No%>]]>
		                    </No>
		                </Select>
		                <RowSeparator>
			                <![CDATA[<%RowSeparator%>]]>
		                </RowSeparator>
		                <ColSeparator>
			                <![CDATA[<%ColSeparator%>]]>
		                </ColSeparator>
		                <RecordSeparator>
			                <![CDATA[<%RecordSeparator%>]]>
		                </RecordSeparator>
		                <Record>
			                <![CDATA[<%Record%>]]>
		                </Record>
		                <Col MaxRecord=""<%MaxRecord%>"">
			                <![CDATA[<%Col%>]]>
		                </Col>
		                <Row MaxCol=""<%MaxCol%>"">
			                <![CDATA[<%Row%>]]>
		                </Row>
		                <All>
			                <![CDATA[<%All%>]]>
		                </All>
                        ");
            result.Replace("<%Yes%>", _yesXml.ToString());
            result.Replace("<%No%>", _noXml.ToString());
            result.Replace("<%RowSeparator%>", rowSeparator.ToString());
            result.Replace("<%ColSeparator%>", colSeparator.ToString());
            result.Replace("<%RecordSeparator%>", _recordSeparatorXml.ToString());
            result.Replace("<%Record%>", record.ToString());
            result.Replace("<%Col%>", col.ToString());
            result.Replace("<%Row%>", row.ToString());
            result.Replace("<%MaxRecord%>", maxRecord);
            result.Replace("<%MaxCol%>", maxCol);
            result.Replace("<%All%>", all.ToString());
            ResultXml = result.ToString();
            #endregion
        }
        private void MakeRecordReplacementCode(Tag tag)
        {
            foreach (Tag childTag in tag.ChildTags)
            {
                if (childTag is Code || (!(childTag is Separator) && childTag.ResultCode == null))
                    continue;

                if (childTag is OutputStatment)
                {
                    string content = Engine.Text.Substring(childTag.ContentIndex, childTag.ContentLength).Replace("\"", "\"\"");
                    if (_repeatCheckList.Contains(content))
                        continue;

                    _statment.Append(@"
                                        replacementPair[@""{#" + content + @"#}""] = new CustomBuild(
                                                                        delegate(DataRow record, int index)
                                                                        {
                                                                            object " + childTag.UniqueName + " = " + childTag.ResultCode + @";
                                                                            if (" + childTag.UniqueName + @" != null)
                                                                                return " + childTag.UniqueName + @".ToString();
                                                                            else
                                                                                return String.Empty;
                                                                        }
                                                                        );
                                                ");
                    _repeatCheckList.Add(content);
                }
                else if (childTag is IfStatment)
                {
                    _complex.Append(@"
                                        replacementPair[""{#" + childTag.UniqueName + @"#}""] = new CustomBuild(
                                                                        delegate(DataRow record, int index)
                                                                        {"
                                                                        + childTag.ResultCode +
                                                                    @"
                                                                            return " + childTag.UniqueName + @";
                                                                        }
                                                                        );
                                                ");
                }
                else if (childTag.ResultCode != null && Regex.IsMatch(childTag.ResultCode, "protected string " + childTag.UniqueName + @"\s+{\s+get\s+"))
                {
                    _complex.Append(@"
                                        replacementPair[""{#" + childTag.UniqueName + @"#}""] = new CustomBuild(
                                                                        delegate(DataRow record, int index)
                                                                        { return " + childTag.UniqueName + @";}
                                                                        );
                                                ");
                }
                else if (childTag is Separator)
                {
                    MakeRecordReplacementCode(childTag);
                }
            }
        }
        private void MakeRecordReplacementXml(Tag tag, StringBuilder result)
        {
            for (int i = tag.ChildTags.Count - 1; i >= 0; i--)
            {
                Tag childTag = tag.ChildTags[i];
                if (result != null)
                    result.Remove(childTag.Index - tag.ContentIndex, childTag.Length);

                if (childTag is OutputStatment)
                {
                    string content = Engine.Text.Substring(childTag.ContentIndex, childTag.ContentLength);
                    result.Insert(childTag.Index - tag.ContentIndex, "{#" + content + "#}");
                }
                else if (childTag is IfStatment || (childTag.ResultCode != null && Regex.IsMatch(childTag.ResultCode, "protected string " + childTag.UniqueName + @"\s+{\s+get\s+")))
                {
                    result.Insert(childTag.Index - tag.ContentIndex, "{#" + childTag.UniqueName + "#}");
                }
                else if (childTag is Separator)
                {
                    _recordSeparatorXml.Append(Engine.Text.Substring(childTag.ContentIndex, childTag.ContentLength));
                    MakeRecordReplacementXml(childTag, _recordSeparatorXml);
                }
                else if (childTag is Select)
                {
                    result.Insert(childTag.Index - tag.ContentIndex, "{#" + childTag.UniqueName + "#}");
                    MakeRecordReplacementXml(childTag, null);
                }
                else if (childTag is Yes)
                {
                    _yesXml.Append(Engine.Text.Substring(childTag.ContentIndex, childTag.ContentLength));
                    MakeRecordReplacementXml(childTag, _yesXml);
                }
                else if (childTag is No)
                {
                    _noXml.Append(Engine.Text.Substring(childTag.ContentIndex, childTag.ContentLength));
                    MakeRecordReplacementXml(childTag, _noXml);
                }
            }
        }

        #region Fields
        private Tag _select;
        private Tag _selectYes;
        private Tag _selectNo;
        private Tag _record;
        private Tag _col;
        private Tag _row;
        private string _id;
        private string _mark;
        private DataRow _module;
        private DataRow _object;
        private StringBuilder _yesXml;
        private StringBuilder _noXml;
        private StringBuilder _recordSeparatorXml;
        private StringBuilder _aliasStatment;
        private StringBuilder _statment;
        private StringBuilder _complex;
        private List<string> _repeatCheckList;
        private string _selectExactly;
        #endregion
    }
}
